{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 120,
   "id": "55b72c7e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "from torch import nn\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "id": "2c3d9e11",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'2.5.1'"
      ]
     },
     "execution_count": 121,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Check PyTorch version\n",
    "torch.__version__"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c55babe3",
   "metadata": {},
   "source": [
    "## 1. Data (prepare and loading)\n",
    "* 表格\n",
    "* 图片\n",
    "* 视频\n",
    "* 音频\n",
    "* 文本\n",
    "机器学习的两个要点：\n",
    "1. 将数据转换为数字\n",
    "2. 构建模型来学习数据中的模式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "id": "6ffd8153",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([[0.0000],\n",
       "         [0.0200],\n",
       "         [0.0400],\n",
       "         [0.0600],\n",
       "         [0.0800],\n",
       "         [0.1000],\n",
       "         [0.1200],\n",
       "         [0.1400],\n",
       "         [0.1600],\n",
       "         [0.1800]]),\n",
       " tensor([[0.3000],\n",
       "         [0.3140],\n",
       "         [0.3280],\n",
       "         [0.3420],\n",
       "         [0.3560],\n",
       "         [0.3700],\n",
       "         [0.3840],\n",
       "         [0.3980],\n",
       "         [0.4120],\n",
       "         [0.4260]]))"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "weight = 0.7\n",
    "bias = 0.3\n",
    "\n",
    "# Create\n",
    "start = 0\n",
    "end = 1\n",
    "step = 0.02\n",
    "\n",
    "X = torch.arange(start, end, step).unsqueeze(dim=1)\n",
    "y = weight * X + bias\n",
    "\n",
    "X[:10], y[:10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "id": "c9d78826",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(50, 50)"
      ]
     },
     "execution_count": 123,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(X), len(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd836748",
   "metadata": {},
   "source": [
    "### 数据集分为训练集和测试集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "id": "ee14a315",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建一个 训练集 和 测试集 的划分\n",
    "train_split = int(0.8 * len(X))\n",
    "X_train, y_train = X[:train_split], y[:train_split]\n",
    "X_test, y_test = X[train_split:], y[train_split:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "id": "8ef0dc44",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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q8dUVVU121+SiouL29wf9tWR6+cfffrppzp+/LjOPvvsrioTCaij184999yjAQMG6Lvf/W53lIkE1ZHrxzRNFRYWas6cOcrNzdVXvvIV3X///QqHw91VNhJER66fCRMmaPPmzdHlbTt37tQrr7yib3zjG91SM5JXd//d3KNLzpqkDh8+rHA4rNzc3Gbjubm52r59e6vH1NTUtLp/TU1Nl9WJxNSR6+cf/fjHP9bgwYNb/CMAe+vItfPaa69pxYoV2rp1azdUiETWketn586d+uMf/6h//dd/1SuvvKIdO3bo+9//vo4fP67S0tLuKBsJoiPXz0033aTDhw/riiuukGVZOnHihGbPns3SNZxWW383h0IhffbZZ+rZs2envh4zOkCCeOCBB7R69Wq9+OKLysrKinc5SGBHjx7V1KlTtXz5cvXv3z/e5SAJNTY2asCAAfr1r3+tsWPHasqUKbrrrrv02GOPxbs0JIHKykrdf//9evTRR7VlyxaVl5dr7dq1uvfee+NdGtAMMzqf079/fzmdTtXW1jYbr62t1cCBA1s9ZuDAgTHtD/vqyPVz0kMPPaQHHnhAGzZs0MUXX9yVZSIBxXrtvP/++9q9e7cmTZoUHWtsbJQk9ejRQ9XV1TrvvPO6tmgkjI782zNo0CClp6fL6XRGxy666CLV1NSooaFBGRkZXVozEkdHrp8FCxZo6tSpuuWWWyRJo0aNUl1dnb73ve/prrvuUloa/x0drWvr7+bs7OxOn82RmNFpJiMjQ2PHjlVFRUV0rLGxURUVFSosLGz1mMLCwmb7S9If/vCHNveHfXXk+pGk//zP/9S9996rdevWady4cd1RKhJMrNfOhRdeqLfffltbt26NPgzDiN7FJi8vrzvLR5x15N+eyy+/XDt27IgGZEl67733NGjQIEJOiunI9fPpp5+2CDMnQ3PkM+lA67r97+YuucVBElu9erWVmZlprVq1yvrrX/9qfe9737P69u1r1dTUWJZlWVOnTrXmzZsX3f/111+3evToYT300EPWtm3brNLSUis9Pd16++234/UWEEexXj8PPPCAlZGRYT3//PPWgQMHoo+jR4/G6y0gTmK9dv4Rd11LbbFeP3v37rX69Olj3XbbbVZ1dbX18ssvWwMGDLB++tOfxustII5ivX5KS0utPn36WL/97W+tnTt3WuvXr7fOO+8864YbbojXW0CcHD161Hrrrbest956y5JkLV261HrrrbesPXv2WJZlWfPmzbOmTp0a3X/nzp1Wr169rB/96EfWtm3brGXLlllOp9Nat25dl9RH0GmFz+ezvvjFL1oZGRnW+PHjrTfffDP63MSJE63p06c32/+5556zLrjgAisjI8P68pe/bK1du7abK0YiieX6GTZsmCWpxaO0tLT7C0fcxfpvz+cRdBDr9fPGG29YBQUFVmZmpnXuueda9913n3XixIlurhqJIpbr5/jx49aiRYus8847z8rKyrLy8vKs73//+9aRI0e6v3DEVSAQaPXvmJPXy/Tp062JEye2OGbMmDFWRkaGde6551pPPPFEl9XnsCzmGAEAAADYC5/RAQAAAGA7BB0AAAAAtkPQAQAAAGA7BB0AAAAAtkPQAQAAAGA7BB0AAAAAtkPQAQAAAGA7BB0AAAAAtkPQAQAAAGA7BB0AAAAAtkPQAQAAAGA7/w+qmJU3QGJ/agAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 1000x700 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def plot_predictions(train_data = X_train,\n",
    "                     train_labels = y_train,\n",
    "                     test_data = X_test,\n",
    "                     test_labels = y_test,\n",
    "                     predictions = None) :\n",
    "    \"\"\"\n",
    "    Plots training data, test data and compares predictions.\n",
    "    \"\"\"\n",
    "    \n",
    "    plt.figure(figsize=(10, 7))\n",
    "    \n",
    "    # Plot training data in blue\n",
    "    plt.scatter(train_data, train_labels, c=\"b\", s=4, label=\"Training data\")\n",
    "    \n",
    "    # Plot test data in green\n",
    "    plt.scatter(test_data, test_labels, c=\"g\", s=4, label=\"Testing data\")\n",
    "    \n",
    "    # Are there predictions?\n",
    "    if predictions is not None :\n",
    "        # Plot the predictions if they exist\n",
    "        plt.scatter(test_data, predictions, c=\"r\", s=4, label=\"Predictions\")\n",
    "        \n",
    "    # Show the Legend\n",
    "    plt.legend(prop={\"size\" : 14})\n",
    "    \n",
    "    \n",
    "plot_predictions()\n",
    "        "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9908163",
   "metadata": {},
   "source": [
    "## 2. 构建第一个 PyTorch 模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "id": "68425bf0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "from torch import nn\n",
    "\n",
    "class LinearRegressionModel(nn.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.weights = nn.Parameter(torch.randn(1,\n",
    "                                                requires_grad=True,\n",
    "                                                dtype=torch.float))\n",
    "        \n",
    "        self.bais = nn.Parameter(torch.randn(1,\n",
    "                                             requires_grad=True,\n",
    "                                             dtype=torch.float))\n",
    "        \n",
    "    # 每个继承于 nn.Module 的模型都必须实现 forward 方法，该方法定义了模型的前向传播逻辑\n",
    "    def forward(self, x: torch.Tensor)->torch.Tensor:\n",
    "        return self.weights * x + self.bais"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f5e560a3",
   "metadata": {},
   "source": [
    "### 两种方法\n",
    "1. 梯度下降法\n",
    "2. 反向传播法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "id": "d6f965e9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<torch._C.Generator at 0x7c85e94954b0>"
      ]
     },
     "execution_count": 127,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.manual_seed(42)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "id": "20b24b0c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([0.3367])"
      ]
     },
     "execution_count": 128,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.randn(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 129,
   "id": "07b6b0ad",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([0.1288, 0.2345])"
      ]
     },
     "execution_count": 129,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.randn(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "id": "fa2b96f0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 0.2303, -1.1229, -0.1863],\n",
       "        [ 2.2082, -0.6380,  0.4617]])"
      ]
     },
     "execution_count": 130,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.randn(2, 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "id": "00aff32e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Parameter containing:\n",
       " tensor([0.3367], requires_grad=True),\n",
       " Parameter containing:\n",
       " tensor([0.1288], requires_grad=True)]"
      ]
     },
     "execution_count": 138,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create a random seed\n",
    "torch.manual_seed(42)\n",
    "\n",
    "# 创建一个模型实例 (subclass of nn.Module)\n",
    "model_0 = LinearRegressionModel()\n",
    "\n",
    "# 检查模型参数\n",
    "list(model_0.parameters())\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "id": "23bd1067",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "OrderedDict([('weights', tensor([0.3367])), ('bais', tensor([0.1288]))])"
      ]
     },
     "execution_count": 139,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# List named parameters\n",
    "model_0.state_dict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "id": "bd473d05",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.7, 0.3)"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "weight, bias"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "40646b7b",
   "metadata": {},
   "source": [
    "### 使用 `torch.inference_mode()` 来预测\n",
    "检查模型预测能力\n",
    "\n",
    "当我们将数据传递给模型时，它将通过模型的“forward（）”方法并使用我们定义的计算产生结果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "id": "aff06411",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([[0.8000],\n",
       "         [0.8200],\n",
       "         [0.8400],\n",
       "         [0.8600],\n",
       "         [0.8800],\n",
       "         [0.9000],\n",
       "         [0.9200],\n",
       "         [0.9400],\n",
       "         [0.9600],\n",
       "         [0.9800]]),\n",
       " tensor([[0.8600],\n",
       "         [0.8740],\n",
       "         [0.8880],\n",
       "         [0.9020],\n",
       "         [0.9160],\n",
       "         [0.9300],\n",
       "         [0.9440],\n",
       "         [0.9580],\n",
       "         [0.9720],\n",
       "         [0.9860]]))"
      ]
     },
     "execution_count": 141,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_test, y_test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 142,
   "id": "258cba87",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[0.3982],\n",
       "        [0.4049],\n",
       "        [0.4116],\n",
       "        [0.4184],\n",
       "        [0.4251],\n",
       "        [0.4318],\n",
       "        [0.4386],\n",
       "        [0.4453],\n",
       "        [0.4520],\n",
       "        [0.4588]], grad_fn=<AddBackward0>)"
      ]
     },
     "execution_count": 142,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_preds = model_0(X_test)\n",
    "y_preds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 145,
   "id": "3f5ecd3b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[tensor([0.3982]),\n",
       " tensor([0.4049]),\n",
       " tensor([0.4116]),\n",
       " tensor([0.4184]),\n",
       " tensor([0.4251]),\n",
       " tensor([0.4318]),\n",
       " tensor([0.4386]),\n",
       " tensor([0.4453]),\n",
       " tensor([0.4520]),\n",
       " tensor([0.4588])]"
      ]
     },
     "execution_count": 145,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "with torch.inference_mode():\n",
    "    y_preds = model_0(X_test)\n",
    "    \n",
    "list(y_preds)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "id": "f5dd293b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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Bq558+aF9HXbsmWLRowYoYqKCjmdTo0dO1ZJSUmKiYlRUVGR1q5dG9L5AAAAWsI1yCXPVR4VbS+SI90RVffoEHRawOsNhBy/P/BcVBR9QaepRpVLlizRzp07dc899+iuu+6q97n77rtPHo+nPcprkdpQtWfPnkY/X15e3uxz1Yarxs7l9/v1n//8R3379g1u27NnjxYtWqQzzjhDxcXF9foKlZWVad68ec1+bSkwVW///v169tlnde2119b73NSpU4MrtgEAALQ11yBXVAWcWkxdawGnsy7k+P3ST1ZWjmpffvmlJDW6otff//739i4nJIMGDVJCQoLWr1/fYLTDNE0VFxc3+1xDhgyR1Ph7Li4u1uHDh+tt27p1q0zTVEZGRoPmqU193ex2u6TGR7aa+ncwTVPvvfdeM98FAABAx0XQaQGXKzBdbfr06Jy2diT9+/eXJL377rv1tj///PN6/fXXw1FSsyUkJOiKK65QeXm58vPz633umWee0ebNm5t9LrfbraSkJC1dulRffPFFcPuhQ4cajHRJdV+3999/v950uq+++kqzZs1q9DW6d+8uSdq1a1eT5/vpv8N9992nTz/9tNnvAwAAoKNi6loLuVzWCji1JkyYoPvvv1+33HKLvF6v+vfvr48//liFhYX6zW9+o5UrV4a7xCPKy8vTmjVrNHPmTK1duzbYR+e1117Tr371K61evVoxMUfP98nJyXr00Uc1adIknX322brqqquUnJys1157TZ06daq3kpxUtxrayy+/rOHDh+uiiy5SeXm5XnvtNV100UXBEZofu/DCC/XSSy/p8ssv169//WslJiZqyJAhGjt2rKZOnaqnnnpKl19+ua688kr16NFDH3zwgTZs2KAxY8Zo1apVrfY1AwAAsCJGdFBPv379tHbtWl100UVas2aNnnzySVVXV+vNN9/U2LFjw13eUaWlpam4uFi//e1v9f777ys/P1979uzRm2++qRNPPFFS4wskNCYrK0uvvPKKTjrpJD399NN6+umnde6552rNmjWNrli3bNky3Xbbbdq/f78KCgr0wQcfKCcnR88//3yj558yZYpmzJihffv26f7779fs2bP18ssvS5LOPPNMvfnmmzrrrLO0cuVKLV26VN26ddN7772n4cOHt/CrAwAA0HHYTNM0w13E0VRUVCg5OVk+n6/JX1IPHjyo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uXr55Zd12223SZKOP/543Xzzzbrzzjtlt9uPua6kpKQG22JjA5em3+8PbquoqJCkeqM5tVJSUpr9ekc6T1Pn2rJli0aMGKGKigo5nU6NHTtWSUlJiomJUVFRkdauXdsg+BzJ9OnTtXDhQqWlpcnlcik1NVUJCQmSAgsYhHIuAAAQXZwDnMr/R37w90lHuiPcJVkSQacFovXirA0Ul19+uV566aVmHdOjRw8VFBTo0Ucf1ebNm/X222+roKBAubm5iouL06xZs9qy5Hpq69+zZ0+DkZPy8vIWnacxjZ3r4Ycf1v79+/Xss8/q2muvrfe5qVOnau3atc1+/T179mjRokU644wzVFxcrM6dOwc/V1ZW1uhoGwAAsA7XIJc8V3lUtL1IjnRHVPzBPBpxj04L1F6c00dOj5ppa1JgKlpSUpL++c9/6tChQyEda7PZdOqpp2ratGl66623JKnectS1Izs/HoFpbUOGDJEkvffeew0+9/777zf7PElJSRowYIC2bNmisrKyBp//+9//3mDbl19+KUnBldVqmabZaD1H+nps3bpVpmkqIyOjXshp6rUBAID1uAa5tCBzQdT8HhmNCDotFI0XZ2xsrG688Ubt2LFDt99+e6Nh59NPPw2OdGzfvj3Y9+XHakc8EhMTg9u6d+8uSdq1a1cbVB5w1VVXKSYmRg899JD27dsX3F5ZWan58+eHdK4JEyaourpac+bMqbf9zTffbPT+nNoRpJ8ud33ffffp008/bbD/kb4eted6//33692X89VXX7XrCBkAAICVMXWtg5k3b542bNigRx99VKtWrdIFF1ygXr16qbS0VJ988ok+/vhjFRcXq1evXtq4caN+85vfaMSIEcEb92t7x8TExCg7Ozt43tpGoXfccYc+++wzJScnq1u3bsFVxFrDoEGDNHPmTN17770aPHiwrrzySsXGxmrlypUaPHiwPv3002YvkjBjxgytXLlSixcv1meffaYLLrhAu3bt0osvvqgxY8Zo1apV9fafOnWqnnrqKV1++eW68sor1aNHD33wwQfasGFDo/ufcsop6tOnj5YvX66EhAT169dPNptNt9xyS3CltpdfflnDhw/XRRddpPLycr322mu66KKLgqNHAAAAaDlGdDqYhIQE/e1vf9OTTz6p3r176+WXX1Z+fr7eeecdpaam6vHHH9fgwYMlScOHD9cf//hH2Ww2rVq1Sg899JCKioqUkZGh9957Ty5X3WjWaaedpqeeeko9e/ZUQUGBZs+erQcffLDV658/f74ee+wx/exnP9MTTzyhF198UVdccYUee+wxSY0vbNCY4447TmvXrtUNN9ygf//738rPz9fmzZu1YsUKXXHFFQ32P/PMM/Xmm2/qrLPO0sqVK7V06VJ169ZN7733noYPH95gf7vdrpUrV+qXv/ylXnjhBc2ZM0ezZ8/W/v37JUnLli3Tbbfdpv3796ugoEAffPCBcnJy9Pzzzx/DVwcAAAC1bKZpmuEu4mgqKiqUnJwsn8/X5C+yBw8e1LZt2zRgwIB6U6rQMaxZs0YXX3yxZsyYofvvvz/c5UQEvicAAIAVNScbSIzoIMrs3bu3wQ3+3377bfDelnHjxoWhKgAA0FFFYxP5joJ7dBBV/vznP+vBBx/UhRdeqD59+mj37t1avXq19uzZo0mTJmnUqFHhLhEAAHQQ0dpEvqMg6CCqnHPOORo2bJjWrFmjb775Rna7Xaeeeqpmz56tm266KdzlAQCADiRam8h3FAQdRJURI0bI4/GEuwwAAICobSLfURB0AAAAgBaobSJftL1IjnQHozkRhqADAAAAtJBrkIuAE6FYdQ0AAACA5RB0AAAAAFgOQQcAAACA5RB0AAAAAFgOQQcAAAAdnlFiKHt1towSI9yloJUQdAAAANChGSWG3MvdKlhXIPdyN2HHIgg6AAAA6NC827zBpp92m11F24vCXRJaAUEHbW779u2y2WyaNGlSve0Oh0M2m63NXjc9PV3p6eltdn4AAGANzgHOYMjxm3450h3hLgmtgKBjMbWh4seP+Ph4paWl6ZprrtG//vWvcJfYaiZNmiSbzabt27eHuxQAABDFXINc8lzl0fSR0+W5ykMDUIuIDXcBaBsDBw7UtddeK0n67rvv9MEHH+iFF17QypUrVVhYqHPPPTfMFUrPPPOMvv/++zY7f2FhYZudGwAAWItrkIuAYzEEHYs68cQTNXfu3Hrb7rrrLs2fP1933nmnioqKwlLXj/385z9v0/MPHDiwTc8PAACAyMXUtQ7klltukSR9+OGHkiSbzSaHw6HS0lJNnDhRvXv3VkxMTL0Q9M4772js2LHq2bOnEhISdNJJJ+muu+5qdCTG7/fr/vvv14knnqjExESdeOKJysvLU01NTaP1HOkeHY/Ho0suuUQ9evRQYmKi0tPTNWHCBH366aeSAvffPP3005KkAQMGBKfpORyO4DmaukensrJSubm5OuWUU5SYmKju3btrzJgxeu+99xrsO3fuXNlsNhUVFen555/X0KFD1alTJ6WmpurWW2/VDz/80OCYl19+WaNHj1avXr2UmJioPn36KCMjQy+//HKj7xUAAACtjxGdDujH4eI///mPRo0ape7du+uqq67SwYMHlZSUJEl6/PHHNW3aNHXr1k1jx45Vr1699M9//lPz58+X1+uV1+tVfHx88Fw33HCDli5dqgEDBmjatGk6ePCgFixYoPfffz+k+m677TYtWLBA3bt317hx49SrVy/t2rVLa9as0bBhw3T66afr97//vZYtW6aPP/5Yt956q7p16yZJR1184ODBg7rwwgu1bt06nXXWWfr973+v8vJyrVixQm+88YZeeOEF/fa3v21w3MKFC7V69Wq53W5deOGFWr16tR599FHt27dPf/7zn4P7Pf7447rpppuUmpqqyy67TD169FBZWZnWrVunV155RZdffnlIXwsAAAC0kNkCCxcuNPv3728mJCSYI0aMMP/xj380uW91dbU5b94884QTTjATEhLMM844w/zb3/4W0uv5fD5Tkunz+Zrc54cffjA///xz84cffgjp3Fazbds2U5KZmZnZ4HNz5swxJZlOp9M0TdOUZEoyJ0+ebB4+fLjevp999pkZGxtrDhkyxNy3b1+9z+Xl5ZmSzAcffDC4zev1mpLMIUOGmN99911w+1dffWX27NnTlGRmZWXVO8/o0aPNn16Cf/3rX01J5uDBgxu87qFDh8yysrLgx1lZWaYkc9u2bY1+Lfr372/279+/3rZ58+aZksz//u//NmtqaoLbN2zYYMbHx5vdunUzKyoqgttzc3NNSWZycrK5efPm4Pbvv//ePPnkk82YmBiztLQ0uP2ss84y4+PjzfLy8gb1/PT9tDW+JwAAgBU1JxuYpmmGPHVtxYoVysnJUW5urjZs2KAhQ4YoMzNTe/bsaXT/u+66S08++aQKCgr0+eefa+rUqbrsssv00UcftSCWRRDDkLKzA88RaMuWLZo7d67mzp2rP/zhD7rgggt09913KzExUfPnzw/uFx8frz/96U+y2+31jn/yySd1+PBhFRQUqEePHvU+N2PGDB1//PF64YUXgtueeeYZSdKcOXN03HHHBbf37dtXt956a7PrfuyxxyRJjzzySIPXjY2NVUpKSrPP1Zinn35acXFxuu++++qNbJ155pnKysrSt99+q1dffbXBcbfeeqsGDRoU/LhTp066+uqrVVNTo/Xr19fbNy4uTnFxcQ3O8dP3AwAAWpdRYih7dTYNPyGpBVPXFixYoClTpmjy5MmSpCeeeEKrVq3S0qVLNXPmzAb7P/vss7rzzjt16aWXSpJuvPFGrVmzRg899JCee+65Yyw/TAxDcrslu13Kz5c8HskVWat0fPnll5o3b56kwC/eKSkpuuaaazRz5kwNHjw4uN+AAQPUs2fPBsd/8MEHkqQ33nij0dXL4uLitHnz5uDHH3/8sSTp/PPPb7BvY9uasm7dOiUkJGj06NHNPqa5KioqtHXrVp166qnq169fg887nU4tXrxYGzdu1IQJE+p9btiwYQ32rz3Ht99+G9x21VVXacaMGTr99NN1zTXXyOl06rzzzgtOBwQAAG3DKDHkXu6W3WZX/j/yWSYaoQWd6upqrV+/XrNmzQpui4mJUUZGhoqLixs9pqqqSomJifW2derUSe+++26Tr1NVVaWqqqrgxxUVFaGU2fa83kDI8fsDz0VFERd0MjMztXr16qPu19QIyTfffCNJ9UZ/jsTn8ykmJqbR0BTKKIzP51Pfvn0VE9P662TUXkdN1ZOamlpvvx9rLKjExga+ffx+f3Db7bffrh49eujxxx/XQw89pAcffFCxsbEaM2aMHn74YQ0YMOCY3wcAAGjIu80bbPhpt9lVtL2IoNPBhfTb5L59++T3+xv8opiSkqKysrJGj8nMzNSCBQv073//WzU1NXrrrbe0cuVK7d69u8nXycvLU3JycvCRlpYWSpltz+msCzl+v/Sjlb6iTVOrntX+Yl9RUSHTNJt81EpOTlZNTY327dvX4Fzl5eXNrqdbt24qKytrcqW2Y1H7npqqp/YaPpbRF5vNpt/97nf68MMPtXfvXr3yyiv6zW9+I4/Ho//6r/+qF4oAAEDrcQ5wBkOO3/TLke4Id0kIszZfXvqRRx7RSSedpFNOOUXx8fG6+eabNXny5CP+xX7WrFny+XzBx65du9q6zNC4XIHpatOnR+S0tdYwcuRISXVT2I5myJAhkqS///3vDT7X2LamjBgxQlVVVVq7du1R9629r6i54SEpKUknnHCCtmzZotLS0gafr11We+jQoc2u90h69OihcePGacWKFbrwwgv1+eefa8uWLa1ybgAAUJ9rkEueqzyaPnI609YgKcSg07NnT9nt9gZ/ES8vL1fv3r0bPeb444/Xq6++qsrKSu3YsUObN29Wly5ddMIJJzT5OgkJCUpKSqr3iDgul7RggSVDjiTddNNNio2N1S233KKdO3c2+Py3335bb0GJ2nta7r77blVWVga3l5aW6pFHHmn2606bNk1S4Ob/2ulztQ4fPlzv2uvevbskhRSEs7KydOjQIc2aNaveiNS//vUvLVu2TMnJyRo3blyzz/dTRUVF9c4rSYcOHQq+l59O4wQAAK3HNcilBZkLCDmQFOI9OvHx8Ro2bJgKCwuDvwzW1NSosLBQN9988xGPTUxMVN++fXXo0CG9/PLLuvLKK1tcNNre6aefrscee0w33nijBg0apEsvvVQDBw7UgQMHtHXrVq1du1aTJk3SE088ISlwI//kyZP11FNPafDgwbrssstUVVWlFStW6Je//KVee+21Zr3upZdeqttvv10PPvigTjrpJF122WXq1auXSktLVVhYqNtvv12///3vJUkXXnihHnzwQd1www26/PLLddxxx6l///4NFhL4sRkzZmjVqlV69tlntWnTJl100UXas2ePVqxYocOHD2vx4sXq2rVri79u48aNU1JSkn75y1+qf//+OnTokN566y19/vnnuuKKK9S/f/8WnxsAAADNF/Kqazk5OcrKytLw4cM1YsQI5efnq7KyMrgK28SJE9W3b1/l5eVJkv7xj3+otLRUQ4cOVWlpqebOnauamhrNmDGjdd8JWt2UKVM0dOhQLViwQO+8847++te/Kjk5WT//+c+VnZ2trKysevsvXrxYJ598shYvXqyFCxeqX79+ysnJ0ZVXXtnsoCNJDzzwgEaNGqWFCxfqpZde0sGDB5WamqoLL7xQF198cXC/X//61/rTn/6kxYsX66GHHtKhQ4c0evToIwadxMREvf3227r//vu1YsUKPfzww+rcubNGjx6tO+64Q+edd17oX6gfycvL0+rVq7Vu3Tr99a9/1XHHHaeBAwfq8ccf13XXXXdM5wYAAEDz2cyfzrNphoULF+qBBx5QWVmZhg4dqkcffTR4T4fD4VB6erqWLVsmSVq7dq1uvPFGbd26VV26dNGll16q++67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",
      "text/plain": [
       "<Figure size 1000x700 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_predictions(predictions=y_preds)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "495079d5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 我们需要衡量模型预测的误差 loss_function\n",
    "loss_fn = nn.L1Loss()\n",
    "# 优化器调整权重和偏置\n",
    "optimizer = torch.optim.SGD(params=model_0.parameters(), \n",
    "                            lr=0.01) # lr = learning rate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "id": "f2890cad",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "L1Loss()"
      ]
     },
     "execution_count": 150,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "loss_fn"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8a2dd115",
   "metadata": {},
   "source": [
    "### 使用 PyTorch 构建一个训练循环和一个测试循环\n",
    "#### 构建训练循环需要做的事\n",
    "1. 遍历训练数据\n",
    "2. 前向传播\n",
    "3. 计算损失\n",
    "4. 优化器梯度清零\n",
    "5. 损失反向传播 - 链式法则求梯度，再求解模型的每个参数相对于损失的梯度\n",
    "6. 优化器更新权重和偏置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 151,
   "id": "d59f5023",
   "metadata": {},
   "outputs": [],
   "source": [
    "# An epoch is one loop through the data...\n",
    "epochs = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "54f1c5df",
   "metadata": {},
   "outputs": [],
   "source": [
    "for epoch in range(epochs):\n",
    "    model_0.train() # 模型训练时会默认打开所有参数的梯度跟踪\n",
    "    \n",
    "    \n",
    "    \n",
    "    \n",
    "    model_0.eval() # 关闭梯度跟踪"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "torch_learn",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
